package top.codedance.iotp.simulator.serialPort;

import cn.hutool.core.util.ClassUtil;
import top.codedance.iotp.common.util.CommandCli;
import top.codedance.iotp.common.util.SystemUtil;
import top.codedance.iotp.simulator.serialPort.configuration.CliCmdOptionsConfig;
import top.codedance.iotp.simulator.serialPort.srs.Simulator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.ini4j.Wini;

import java.io.File;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SimulatorApplication {

    private static ExecutorService workerPool = Executors.newFixedThreadPool(2); //工作任务线程池
    public static CommandCli commandCli; //命令解析工具
    public static Wini ini = null; //ini文件读取器
    private static Logger logger;
    public static Simulator aimulator;
    public static Simulator uaimulator;
    private static final String AR_PACKAGE = "top.codedance.iotp.simulator.serialPort.srs.";
    private static final String AR_U_PACKAGE = "top.codedance.iotp.simulator.serialPort.urs.";

    public static void main(String[] args) {
        commandCli = new CommandCli(args, CliCmdOptionsConfig.getCmds());
        logger = getLogger(SimulatorApplication.class);
        logger.setLevel(Level.toLevel(SimulatorApplication.commandCli.getArg("logLevel", "ERROR")));
        String sr = SimulatorApplication.commandCli.getArg("simulator", "simple.Loop");
        String classpath = AR_PACKAGE + sr;
        int bootNumber = 0;
        try {
            aimulator = (Simulator)Class.forName(classpath).newInstance();
            bootNumber++;
        }catch (Exception e){
            logger.debug(e.getMessage());
        }
        String ur = SimulatorApplication.commandCli.getArg("udpSimulator", "simple.Loop");
        String uclasspath = AR_U_PACKAGE + ur;
        try {
            uaimulator = (Simulator)Class.forName(uclasspath).newInstance();
            bootNumber++;
        }catch (Exception e){
            logger.debug(e.getMessage());
        }
        if(bootNumber == 0){
            info("Aimulator not found.");
            info("simulator value: ");
            Set<Class<?>> classes = ClassUtil.scanPackageBySuper(AR_PACKAGE.substring(0, AR_PACKAGE.length() -1), Simulator.class);
            for (Class<?> c : classes) {
                info("\t" + c.getName().replace(AR_PACKAGE, ""));
            }
            info("UDPSimulator value: ");
            Set<Class<?>> uclasses = ClassUtil.scanPackageBySuper(AR_U_PACKAGE.substring(0, AR_U_PACKAGE.length() -1), Simulator.class);
            for (Class<?> c : uclasses) {
                info("\t" + c.getName().replace(AR_U_PACKAGE, ""));
            }
            System.exit(0);
        }
        initIniConfig();
        ComServer cs = new ComServer();
        workerPool.submit(cs);
        UdpServer us = new UdpServer();
        workerPool.submit(us);
        try {
            while (true){
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            logger.info("thread pool finished.");
        } finally {
            cs.close();
            us.close();
            info("Aimulator is over.");
        }
    }

    /**
     * 获取log对象并动态设置日志级别
     *
     * @param clazz
     * @return
     */
    public static Logger getLogger(Class<?> clazz) {
        Logger logger = Logger.getLogger(clazz);
        logger.setLevel(Level.toLevel(SimulatorApplication.commandCli.getArg("logLevel", "ERROR")));
        return logger;
    }

    /**
     * 读取ini配置文件
     */
    public static void initIniConfig() {
        String runtimeDirPath = SystemUtil.getRuntimeDirPath(SimulatorApplication.class);
        String iniFilePath = runtimeDirPath + "init.ini";
        File f = new File(iniFilePath);
        if (f.exists()) {
            try {
                ini = new Wini(f);
            } catch (IOException e) {
                logger.debug("Ini file configure fail.");
            }
        } else {
            try {
                f.createNewFile();
                ini = new Wini(f);
            } catch (Exception e) {
                logger.debug("Create ini file fail.");
            }
        }
    }

    public static void info(String msg){
        System.out.println(msg);
    }
}
